#version 450 core

layout (location = 0) in vec3 a_Position;
layout (location = 1) in vec4 a_Color;
layout (location = 2) in vec3 a_Normal;
layout (location = 3) in vec2 a_TexCoord;
layout (location = 4) in vec3 a_Tangent;
layout (location = 5) in vec3 a_Bitangent;

layout (location = 6) in ivec4 a_BoneIds;
layout (location = 7) in vec4 a_Weights;

layout (location = 8) in float a_TexIndex;
layout (location = 9) in float a_TilingFactor;
layout (location = 10) in int a_EntityID;

layout (location = 0) uniform mat4 u_Projection;
layout (location = 1) uniform mat4 u_Model;
layout (location = 2) uniform mat4 u_View;
layout (location = 3) uniform mat4 u_DepthMVP;
layout (location = 4) uniform mat4 u_DepthBiasMVP;
layout (location = 5) uniform mat4 NormalOut;
layout (location = 6) uniform int HasAnim;

const int MAX_BONES = 200;
const int MAX_BONE_INFLUENCE = 4;
layout (location = 23) uniform mat4 finalBonesMatrices[MAX_BONES];

struct VertexOutput
{
	vec3 Normal;
	vec4 Color;
	vec2 TexCoord;
    float TilingFactor;
    vec4 ShadowCoord;
};

layout (location = 0) out VertexOutput Output;
layout (location = 5) out float v_TexIndex;
layout (location = 6) out int v_EntityID;
layout (location = 7) out vec3 WorldPos;

void main()
{    
    vec4 totalPosition = vec4(0.0f);

    vec3 localNormal = vec3(0.0f);

    if(1==HasAnim){
        for(int i = 0 ; i < MAX_BONE_INFLUENCE ; i++)
        {
            if(a_BoneIds[i] == -1){
                if(i == 0){
                    totalPosition = vec4(a_Position,1.0f);
                    localNormal = a_Normal;
                }
                continue;
            }
        
            vec4 localPosition = finalBonesMatrices[a_BoneIds[i]] * vec4(a_Position,1.0f);
            totalPosition += localPosition * a_Weights[i];
        
            localNormal += mat3(finalBonesMatrices[a_BoneIds[i]]) * mat3(NormalOut) * a_Normal * a_Weights[i];
        }
    }
    else{
        totalPosition = vec4(a_Position,1.0f);
        localNormal = mat3(NormalOut) * a_Normal;
    }

    Output.TexCoord = a_TexCoord;
    Output.Normal = localNormal;
    Output.Color = a_Color;
    Output.TilingFactor = a_TilingFactor;
	v_TexIndex = a_TexIndex;
	v_EntityID = a_EntityID;

    WorldPos = (u_Model * totalPosition).xyz;
    gl_Position =  u_Projection * u_View * u_Model * totalPosition;

    Output.ShadowCoord = u_DepthBiasMVP * u_Model * totalPosition;
}

